//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include <iostream>
#include <fstream>

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include "libraries.h"

#include "DisProtProcessResult.h"
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define LENGHTINLINE  100000
#define NUMBERSEQ     1
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
struct fasta {

  char  *id;
  char  *sequence;

  fasta() {
    this->id       = NULL;
    this->sequence = NULL;
  }
  
  ~fasta() {
    if (this->id)       delete[] this->id;
    if (this->sequence) delete[] this->sequence;
  }

};

#define fasta struct fasta
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void trim(char *text) {

  int i, j;
  for (i = 0, j = 0; i < strlen(text); i++)
    if ((text[i] != '\n') && (text[i] != '\r'))
      text[j++] = text[i];
  text[j] = '\0';

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void Ctrim(char *text) {

  int i, j;
  for (i = 0, j = 0; i < strlen(text); i++)
    if ((text[i] != '\n') && (text[i] != '\r') && (text[i] != ' '))
      text[j++] = text[i];
  text[j] = '\0';

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
char* SplitColumn(char* buffer, int position, const char* characters) {

  if (!buffer || !characters || (position <= 0)) return NULL;

  char *part = strtok(buffer, characters);
  if (position == 1) return part;

  int tmpPosition = 1;
  do {
    part = strtok(NULL, characters);
    tmpPosition++;
  } while (part && (tmpPosition != position));

  return part;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
int main (int argc, char** argv) {

  String* namefileIn    = NULL;
  String* namefileOut   = NULL;
  String* directoryVSL2 = NULL;

  if (argc < 3) {
    cout << "Error in the input parameters! Must by like: " << endl;
    cout << "./DisProt <input file> <output file> <Directory VSL2>" << endl;
    return 0;
  }
  else {
    cout << "---------------------------------------------------------------------------------" << endl;
    cout << "     Input File : " << argv[1] << endl;
    cout << "    Output File : " << argv[2] << endl;
    cout << " Directory VSL2 : " << argv[3] << endl;
    cout << "---------------------------------------------------------------------------------" << endl;
    namefileIn    = new String(argv[1]);
    namefileOut   = new String(argv[2]);
    directoryVSL2 = new String(argv[3]);
  }

  fstream           fileIn, fileOut, fileTmp;
  char              buffer[LENGHTINLINE + 1], bufferA[LENGHTINLINE + 1], bufferB[LENGHTINLINE + 1];
  
  TListE <String>*  columns = new TListE <String> ();

  fileIn.open(namefileIn->Out(),   fstream::in);
  fileOut.open(namefileOut->Out(), fstream::out);
  
  if (!fileIn.is_open() || !fileOut.is_open()) {
    
    if (namefileIn)    delete namefileIn;
    if (namefileOut)   delete namefileOut;
    if (directoryVSL2) delete directoryVSL2;
    
    if (columns)       delete columns;
    
    return 0;
    
  }
  
  while (!fileIn.eof()) {
    
    fileIn.getline(bufferA, LENGHTINLINE);
    fileIn.getline(bufferB, LENGHTINLINE);

    trim(bufferA); Ctrim(bufferB);
    
    DisProtProcessResult* disProtProcessResult = new DisProtProcessResult ();
    
    disProtProcessResult->IdInput(bufferA);
    disProtProcessResult->Sequence()->In(bufferB);
    
    fileTmp.open("tmpSequence.flat", fstream::out);
    if (fileTmp.is_open()) {

      fileTmp << bufferB;
      fileTmp.close();
      
      sprintf(buffer, "java -jar %s/VSL2.jar -s:tmpSequence.flat > tmpSequence.result", directoryVSL2->Out());
      int res = system(buffer);
      
      fileTmp.open("tmpSequence.result", fstream::in);
      if (fileTmp.is_open()) {
        
        bool condStart = false;
        
        while (!fileTmp.eof()) {
          
          fileTmp.getline(buffer, LENGHTINLINE);
          
          condStart = (condStart && strstr(buffer, "============"))?false:condStart;
          if (condStart)
            disProtProcessResult->AddResidueDatas(buffer);
          condStart = (strstr(buffer, "------------"))?true:condStart;
          
        }
      
        fileTmp.close();
      
      }
      
      res = system("rm tmpSequence.flat tmpSequence.result");
    
    }
    
    fileOut << ">" << disProtProcessResult->Id()->Out()            << endl;
    fileOut << "<" << disProtProcessResult->Sequence()->Out()      << endl;
    fileOut << "+" << disProtProcessResult->SeqPrediction()->Out() << endl;
    fileOut << "-";
    for (int i = 0; i < disProtProcessResult->ProbPrediction()->Length(); i++)
      fileOut << ((!i)?"":",") << *(disProtProcessResult->ProbPrediction()->Get(i));
    fileOut << endl;
    
    cout << ">" << disProtProcessResult->Id()->Out()            << endl;
    cout << "<" << disProtProcessResult->Sequence()->Out()      << endl;
    cout << "+" << disProtProcessResult->SeqPrediction()->Out() << endl;
    cout << "-";
    for (int i = 0; i < disProtProcessResult->ProbPrediction()->Length(); i++)
      cout << ((!i)?"":",") << *(disProtProcessResult->ProbPrediction()->Get(i));
    cout << endl;
    
    if (disProtProcessResult) delete disProtProcessResult;

  }
  
  fileIn.close();
  fileOut.close();

  if (namefileIn)    delete namefileIn;
  if (namefileOut)   delete namefileOut;
  if (directoryVSL2) delete directoryVSL2;
  
  if (columns)       delete columns;
 
  return 1;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//


